﻿using System;
using System.Collections.Generic;
using System.Linq;
using Autodesk.Revit.DB;
using Autodesk.Revit.UI;
using YArchitech.Revit;
using YArchitech.Revit.RevitExtension;
using YJKRevitKernel.RevitDimensionUtility;
using YJKGeometryFuncs;
using YJKRevitDimensionText.DimCreator;
using YJKRevitDimensionText.OneKeyPlanDim.DimesionDataEx;
using YJKRevitDimensionText.OneKeyPlanDim.Utility.XDataUtils;

namespace YJKRevitDimensionText.OneKeyPlanDim.OutWallThreeDim
{
	public class OutWallThickDimManager
	{
		public Dictionary<ElementId, ElementId> DicWallDim
		{
			get
			{
				return this.m_dicWallIdToDimId;
			}
		}

		public OutWallThickDimManager(UIApplication uiApp, Autodesk.Revit.DB.Document doc, Autodesk.Revit.DB.View view, List<Wall> lstWall, List<Grid> lstGrid, List<WallDataEx> lstWallDataEx = null)
		{
			this.m_uiApp = uiApp;
			this.m_doc = doc;
			this.m_view = view;
			this.m_lstOutWall = lstWall;
			this.m_lstGrid = lstGrid;
			this.m_lstWallDataEx = lstWallDataEx;
		}

		public List<Dimension> CreateOutWallThickDim()
		{
			List<Dimension> list = new List<Dimension>();
			try
			{
				List<List<Wall>> list2 = new List<List<Wall>>();
				this.GetGroupWallArr(list2);
				foreach (List<Wall> list3 in list2)
				{
					if (list3.Count >= 1)
					{
						Wall wall = list3.First<Wall>();
						if (!ElementStringXDataUtil.HasExistDimesion(new List<Wall>
						{
							wall
						}, this.m_view))
						{
							XYZ xyz = DimPublicFunc.To2d(WallOperattionUtil.GetWallLocationCenter(wall));
							XYZ xyz2 = wall.Orientation.Normalize();
							XYZ xyz3 = xyz - xyz2 * 100.0;
							XYZ xyz4 = xyz + xyz2 * 100.0;
							Line crossLine = Line.CreateBound(xyz3, xyz4);
							List<ReferenceInfo> list4 = new List<ReferenceInfo>();
							ReferenceInfo referenceInfo = null;
							ReferenceInfo referenceInfo2 = null;
							WallOperattionUtil.GetOutWallThicknessRef(this.m_lstWallDataEx, this.m_uiApp, wall, crossLine, ref referenceInfo, ref referenceInfo2);
							if (referenceInfo != null && referenceInfo2 != null)
							{
								list4.Add(referenceInfo);
								list4.Add(referenceInfo2);
							}
							ReferenceInfo baoWenLayerReference = this.GetBaoWenLayerReference(wall, crossLine);
							if (baoWenLayerReference != null)
							{
								list4.Add(baoWenLayerReference);
							}
							ReferenceInfo nearestGridRef = this.GetNearestGridRef(wall, crossLine);
							if (nearestGridRef != null)
							{
								list4.Add(nearestGridRef);
							}
                            list4.Sort(new YJKRevitDimensionText.DimCreator.DistanceComparer(xyz3));
							for (int i = 0; i < list4.Count; i++)
							{
								ReferenceInfo referenceInfo3 = list4[i];
								for (int j = i + 1; j < list4.Count; j++)
								{
									if (referenceInfo3.ThePosition.DistanceTo(list4[j].ThePosition) < 0.0032)
									{
										list4.RemoveAt(j);
										j--;
									}
								}
							}
							if (list4.Count > 1)
							{
								ReferenceArray referenceArray = new ReferenceArray();
								foreach (ReferenceInfo referenceInfo4 in list4)
								{
									referenceArray.Append(referenceInfo4.TheReference);
								}
								XYZ outWallThickDimPoint = WallOperattionUtil.GetOutWallThickDimPoint(wall, this.m_lstWallDataEx);
								XYZ vtDim = wall.Orientation.Normalize();
								Dimension dimension = null;
								if (outWallThickDimPoint != null)
								{
									dimension = this.CreateSizeDim(referenceArray, vtDim, outWallThickDimPoint);
								}
								if (dimension != null)
								{
									list.Add(dimension);
									this.m_dicWallIdToDimId.Add(wall.Id, dimension.Id);
									ElementStringXDataUtil.WriteXData(wall, dimension.UniqueId);
									ElementStringXDataUtil.WriteOneKeyPlaneDimMark(dimension);
								}
							}
						}
					}
				}
			}
			catch (Exception)
			{
			}
			return list;
		}

		private Reference GetNearestGridRef2(Wall wall)
		{
			Reference result = null;
			double num = 6.5616797900262469;
			XYZ xyz = WallOperattionUtil.GetWallLocationCenter(wall) + wall.Orientation.Normalize().Multiply(wall.Width / 2.0);
			XYZ xyz2 = xyz + wall.Orientation.Normalize().Multiply(num);
			Curve zeroHeightCurve = OutWallThreeDimManager.GetZeroHeightCurve(Line.CreateBound(xyz, xyz2));
			double num2 = double.MaxValue;
			foreach (Grid grid in this.m_lstGrid)
			{
				Line line = grid.Curve as Line;
				if (!(null == line) && Geometry.IsVertical(wall.Orientation.Normalize(), line.Direction.Normalize()))
				{
					IntersectionResultArray intersectionResultArray = null;
					Curve zeroHeightCurve2 = OutWallThreeDimManager.GetZeroHeightCurve(grid.Curve);
					zeroHeightCurve.Intersect(zeroHeightCurve2, out intersectionResultArray);
					if (intersectionResultArray != null && intersectionResultArray.Size == 1)
					{
						double num3 = intersectionResultArray.get_Item(0).XYZPoint.DistanceTo(xyz);
						if (num3 < num2)
						{
							GridOperationUtil.GetGridDimRef(this.m_uiApp, grid, out result);
							num2 = num3;
						}
					}
				}
			}
			return result;
		}

		private ReferenceInfo GetNearestGridRef(Wall wall, Line crossLine)
		{
			Reference reference = null;
			XYZ xyz = null;
			XYZ wallLocVector = WallOperattionUtil.GetWallLocVector(wall);
			double num = 6.5616797900262469;
			XYZ xyz2 = WallOperattionUtil.GetWallLocationCenter(wall);
			xyz2 = DimPublicFunc.To2d(xyz2);
			XYZ xyz3 = xyz2 + wall.Orientation.Normalize().Multiply(num);
			Line line = Line.CreateBound(xyz2, xyz3);
			line.MakeUnbound();
			double num2 = double.MaxValue;
			foreach (Grid grid in this.m_lstGrid)
			{
				if (!grid.IsHidden(this.m_uiApp.ActiveUIDocument.ActiveView))
				{
					Line line2 = grid.Curve as Line;
					if (!(null == line2) && Geometry.IsVertical(wall.Orientation.Normalize(), line2.Direction.Normalize()))
					{
						Curve zeroHeightCurve = OutWallThreeDimManager.GetZeroHeightCurve(grid.Curve);
						IntersectionResultArray intersectionResultArray = null;
						line.Intersect(zeroHeightCurve, out intersectionResultArray);
						if (intersectionResultArray != null && intersectionResultArray.Size == 1)
						{
							XYZ xyzpoint = intersectionResultArray.get_Item(0).XYZPoint;
							double num3 = xyzpoint.DistanceTo(xyz2);
							if (num3 < num2)
							{
								GridOperationUtil.GetGridDimRef(this.m_uiApp, grid, out reference);
								xyz = Geometry.CalculateFootPoint(crossLine, xyzpoint);
								num2 = num3;
							}
						}
					}
				}
			}
			if (reference != null)
			{
				Line line3 = Line.CreateBound(xyz, xyz + wallLocVector.Multiply(0.0032808398950131233));
				reference = this.m_doc.Create.NewDetailCurve(this.m_doc.ActiveView, line3).GeometryCurve.Reference;
				return new ReferenceInfo(reference, xyz);
			}
			return null;
		}

		private ReferenceInfo GetBaoWenLayerReference(Wall wall, Line crossLine)
		{
			Reference reference = null;
			XYZ xyz = null;
			double wallBaoWenLayerThick = WallOperattionUtil.GetWallBaoWenLayerThick(wall);
			Curve curve = null;
			Curve curve2 = null;
			WallOperattionUtil.GetWallWidthLocationCurve(wall, out curve, out curve2);
			XYZ wallLocVector = WallOperattionUtil.GetWallLocVector(wall);
			if (!Geometry.IsEqual(wallBaoWenLayerThick, 0.0))
			{
				if (null != curve)
				{
					XYZ xyz2 = Geometry.CalculatMidPoint(curve as Line);
					XYZ xyz3 = -wall.Orientation.Normalize().Multiply(wallBaoWenLayerThick);
					XYZ xyz4 = crossLine.Project(xyz2).XYZPoint + xyz3;
					XYZ xyz5 = xyz4 + wallLocVector.Normalize().Multiply(0.0032808398950131233);
					Line line = Line.CreateBound(xyz4, xyz5);
					reference = this.m_doc.Create.NewDetailCurve(this.m_doc.ActiveView, line).GeometryCurve.Reference;
					xyz = Geometry.CalculateFootPoint(crossLine, xyz4);
				}
			}
			else
			{
				List<DetailCurve> list = new List<DetailCurve>();
				FilteredElementCollector filteredElementCollector = new FilteredElementCollector(this.m_doc);
				filteredElementCollector.OfCategory(BuiltInCategory.OST_Lines).WhereElementIsNotElementType();
				foreach (Element element in filteredElementCollector)
				{
					DetailCurve detailCurve = element as DetailCurve;
					if (detailCurve != null && detailCurve.GeometryCurve is Line)
					{
						XYZ xyz6 = (detailCurve.GeometryCurve as Line).Direction.Normalize();
						XYZ wallLocVector2 = WallOperattionUtil.GetWallLocVector(wall);
						if (Geometry.IsParallel(xyz6, wallLocVector2))
						{
							list.Add(detailCurve);
						}
					}
				}
				double num = 0.65616797900262469;
				if (null != curve)
				{
					XYZ xyz7 = Geometry.CalculatMidPoint(curve as Line);
					XYZ xyz8 = xyz7 + wall.Orientation.Normalize().Multiply(num);
					Line line2 = Line.CreateBound(xyz7, xyz8);
					double num2 = double.MaxValue;
					foreach (DetailCurve detailCurve2 in list)
					{
						IntersectionResultArray intersectionResultArray = null;
						line2.Intersect(detailCurve2.GeometryCurve, out intersectionResultArray);
						if (intersectionResultArray != null && intersectionResultArray.Size == 1)
						{
							XYZ xyzpoint = intersectionResultArray.get_Item(0).XYZPoint;
							double num3 = xyzpoint.DistanceTo(xyz7);
							if (num3 < num2)
							{
								reference = detailCurve2.GeometryCurve.Reference;
								num2 = num3;
								xyz = Geometry.CalculateFootPoint(crossLine, xyzpoint);
							}
						}
					}
					if (reference != null)
					{
						XYZ xyz9 = xyz;
						XYZ xyz10 = xyz9 + wallLocVector.Normalize().Multiply(0.0032808398950131233);
						Line line3 = Line.CreateBound(xyz9, xyz10);
						reference = this.m_doc.Create.NewDetailCurve(this.m_doc.ActiveView, line3).GeometryCurve.Reference;
					}
				}
			}
			if (reference != null)
			{
				return new ReferenceInfo(reference, xyz);
			}
			return null;
		}

		private void GetGroupWallArr(List<List<Wall>> lstWallArr)
		{
			foreach (Wall wall in this.m_lstOutWall)
			{
				if (!this.HasGroup(wall, lstWallArr) && !this.IsWallLessLength(wall, 3.2808398950131235))
				{
					List<Wall> list = new List<Wall>();
					list.Add(wall);
					foreach (Wall wall2 in this.m_lstOutWall)
					{
						if (wall2.Id.IntegerValue != wall.Id.IntegerValue && !this.IsWallLessLength(wall, 3.2808398950131235))
						{
							double twoWallDistance = WallOperattionUtil.GetTwoWallDistance(wall, wall2);
							if (wall2.Width == wall.Width && Geometry.IsEqual(twoWallDistance, 0.0, 1E-07))
							{
								list.Add(wall2);
							}
						}
					}
					lstWallArr.Add(list);
				}
			}
		}

		private bool HasGroup(Wall wall, List<List<Wall>> lstWallArr)
		{
			try
			{
				foreach (List<Wall> list in lstWallArr)
				{
					foreach (Wall wall2 in list)
					{
						if (wall.Id.IntegerValue == wall2.Id.IntegerValue)
						{
							return true;
						}
					}
				}
			}
			catch (Exception)
			{
				return false;
			}
			return false;
		}

		private bool IsWallLessLength(Wall wall, double dCmpVale = 0.0)
		{
			try
			{
				if (Geometry.LessThan(RevitElementExtension.GetCurveLength(wall, BuiltInParameter.CURVE_ELEM_LENGTH) * 1000.0, dCmpVale * 304.8, 1E-07))
				{
					return true;
				}
			}
			catch (Exception)
			{
				return false;
			}
			return false;
		}

		private Dimension CreateSizeDim(ReferenceArray refArr, XYZ vtDim, XYZ ptDim)
		{
			Line line = YJKLineEx.YJKGetBound(ptDim, ptDim + vtDim * 10.0);
			DimensionType dimensionType = RevitDimensionUtiltyMethod.GetDimensionType(this.m_doc, 0, null);
			return this.m_doc.Create.NewDimension(this.m_view, line, refArr, dimensionType);
		}

		private List<Wall> m_lstOutWall;

		private List<Grid> m_lstGrid;

		private Document m_doc;

		private UIApplication m_uiApp;

		private Autodesk.Revit.DB.View m_view;

		private List<WallDataEx> m_lstWallDataEx = new List<WallDataEx>();

		private Dictionary<ElementId, ElementId> m_dicWallIdToDimId = new Dictionary<ElementId, ElementId>();

		private const double m_d1000MM = 3.2808398950131235;
	}
}
